﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;

using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace HighDivePrinter.Model
{
    /// <summary>
    /// List that keeps track of the judges in a contest.
    /// </summary>
    /// 
    [Serializable()]
    public class JudgeList : IJudgeList
    {
        private BindingList<Judge> _listJudge;

        //private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        #region Properties

        public BindingList<Judge> ListJudge
        {
            get { return _listJudge; }
            set { _listJudge = value; }
        } 

        /// <summary>
        /// The number of judges in the contest
        /// </summary>
        public int NumberOfJudges { get; set; }

        private readonly Random _rnd = new Random(DateTime.Now.Millisecond);

        #endregion

        #region Public Methods

        /// <summary>
        /// Adds a judge to the list.
        /// Throws an exception if the list is full.
        /// </summary>
        /// <param name="judge">A judge who will be added to the list</param>
       /* public new void Add(Judge judge)
        {
            if (Count < NumberOfJudges)
            {
                if (judge.IdString == null)
                {
                    do
                    {
                        judge.IdString = _generateIdString();
                    } while (!_guaranteeGeneratedIdStringIsUnique(judge.IdString));
                }

                base.Add((judge));
               if (Log.IsDebugEnabled)
                {
                    Log.Debug("Adding Judge with IdNumber " + judge.IdNumber + " to JudgeList");
                }
            }
            else
            {
                throw new JudgeListException("List is full");
            }
        }*/

        /// <summary>
        /// Generates strings for judgments login. If the list is not full thrown an exception.
        /// </summary>
        /// <returns>Array of strings for each judge</returns>
        /*public void GenerateIdStrings()
        {
            if (Count == NumberOfJudges)
            {
               if (Log.IsInfoEnabled)
                {
                    Log.Info("Generating IdStrings for Judges");
                }

                for (int i = 0; i < NumberOfJudges; i++)
                {
                    string idString;

                    do
                    {
                        idString = _generateIdString();
                    } while (!_guaranteeGeneratedIdStringIsUnique(idString));


                    this[i].IdString = idString;

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("IdString " + this[i].IdString + " generated for judge " + this[i].IdNumber);
                    }
                }
            }
           else
            {
                throw new JudgeListException("judge list is not full");
            }
        }*/

        #endregion

        #region Private Methods

      /*  private bool _guaranteeGeneratedIdStringIsUnique(string idString)
        {
            return this.All(judge => idString != judge.IdString);
        }*/

        /// <summary>
        /// Generates a random 5-letter string using symbols A-Z, a-z, 0-9
        /// </summary>
        /// <returns>A random 5-letter string</returns>
        private string _generateIdString()
        {
            
            StringBuilder builder = new StringBuilder(5);

            for (int j = 0; j < 5; j++)
            {
                int randomNumber = _rnd.Next() % 3;
                switch (randomNumber)
                {
                    case 0:
                        randomNumber = _rnd.Next() % 10 + 48;
                        break;
                    case 1:
                        randomNumber = _rnd.Next() % 26 + 65;
                        break;
                    case 2:
                        randomNumber = _rnd.Next() % 26 + 97;
                        break;
                }
                builder.Append(Convert.ToChar(randomNumber));
            }
            return builder.ToString();
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Creates an object of class JudgeList
        /// </summary>
        /// <param name="numberOfJudges">Number of judges list can at most contain. Default = 5</param>
        public JudgeList(int numberOfJudges = 5)
        {
            NumberOfJudges = numberOfJudges;
           
        }
        public JudgeList()
        {
            ListJudge = new BindingList<Judge>();
        }

        #endregion

        #region IJudgeList Members

        void IJudgeList.AddJudgeList(Judge j)
        {
            _listJudge.Add(j);
        }

        void IJudgeList.RemoveJudgeList(int index)
        {
            _listJudge.RemoveAt(index);
        }

        void IJudgeList.SaveJudgeList()
        {
            Stream stream = new FileStream("Judges.xml", FileMode.Create, FileAccess.Write, FileShare.Write);
            XmlSerializer xs = new XmlSerializer(typeof(JudgeList));
            xs.Serialize(stream, this);
            stream.Close();
        }

        void IJudgeList.ReadJudgeList()
        {
            Stream stream = new FileStream("Judges.xml", FileMode.Open, FileAccess.Read, FileShare.Read);
            XmlSerializer xs = new XmlSerializer(typeof(JudgeList));
            JudgeList dt = (JudgeList)xs.Deserialize(stream);

            _listJudge.Clear();
            foreach (var d in dt.ListJudge)
            {
               _listJudge.Add(d);
            }
            stream.Close();
        }

        #endregion
    }
}
